package com.fzb.forum4j.dao.impl;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.persistence.Id;

import org.apache.log4j.Logger;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.stereotype.Repository;

import com.fzb.forum4j.dao.api.IBaseDao;
import com.fzb.forum4j.po.Category;
import com.fzb.forum4j.po.QueryMode;

@Repository("hibBaseImpl")
public class HibBaseImpl<T> implements IBaseDao<T>{

	private T t;
	
	
	public Logger log = Logger.getLogger(getClass());
	
	private Session session;
	@Resource(name="sessionFactory")
	private SessionFactory sessionFactory;
	
	public Session getSession() {
		if(session==null){
			return sessionFactory.getCurrentSession();
		}
		return session;
	}

	public SessionFactory getSessionFactory() {
		return sessionFactory;
	}

	@Override
	public Boolean modifyEntity(T t) {
		getSession().update(t);
		return true;
	}


	/**
	 * 条件的查询
	 * @param qmd
	 * @param qarea
	 * @param qwhere
	 * @param count
	 * @param arg(有条件的查询对应的参数)
	 */
	public void QueryDataByQmd(QueryMode<T> qmd, String qarea,
			String qwhere,String count,Object arg) {
		String obj=qmd.getT().getClass().getSimpleName();
		count="select count(t."+count+") from "+obj+" t where "+qwhere;
		Query queryCount=getSession().createQuery(count).setProperties(arg);
		System.out.println(queryCount);
		long records=(Long) queryCount.uniqueResult();
		if(records==0){
			qmd.getData().put("404", "没有数据");
			return;
		}
		String rows="select new map("+qarea+") from "+obj+" t where "+qwhere;
		Query queryRows=getSession().createQuery(rows).setProperties(arg);
		qmd.getData().put("rows", queryRows.setMaxResults(qmd.getRows()).setFirstResult(qmd.getStartRecord()).list());
		qmd.getData().put("page", qmd.getPage());
		qmd.getData().put("records",records);
		qmd.getData().put("total",(int)Math.ceil(records/(qmd.getRows()*1.0)));
	}
	
	public void QueryDataByQmd(QueryMode qmd, String qarea,
			String qwhere,String count,Object arg,String obj) {
		count="select count(t."+count+") from "+obj+" t where "+qwhere;
		Query queryCount=getSession().createQuery(count).setProperties(arg);
		System.out.println(queryCount);
		long records=(Long) queryCount.uniqueResult();
		if(records==0){
			qmd.getData().put("404", "没有数据");
			return;
		}
		String rows="select new map("+qarea+") from "+obj+" t where "+qwhere;
		Query queryRows=getSession().createQuery(rows).setProperties(arg);
		qmd.getData().put("rows", queryRows.setMaxResults(qmd.getRows()).setFirstResult(qmd.getStartRecord()).list());
		qmd.getData().put("page", qmd.getPage());
		qmd.getData().put("records",records);
		qmd.getData().put("total",(int)Math.ceil(records/(qmd.getRows()*1.0)));
	}
	
	/**
	 * 默认情况下没有带条件的查询
	 * @param qmd 
	 * @param qarea
	 * @param qwhere
	 * @param count(根据count的字段来统计符合要求的条件)
	 */
	public void QueryDataByQmd(QueryMode<T> qmd, String qarea,
			String qwhere,String count){
		String obj=qmd.getT().getClass().getSimpleName();
		count="select count(t."+count+") from "+obj+" t where "+qwhere;
		Query queryCount=getSession().createQuery(count);
		long records=(Long) queryCount.uniqueResult();
		if(records==0){
			qmd.getData().put("404", "没有数据");
			return;
		}
		String rows="select new map("+qarea+") from "+obj+" t where "+qwhere;
		Query queryRows=getSession().createQuery(rows);
		qmd.getData().put("rows", queryRows.setMaxResults(qmd.getRows()).setFirstResult(qmd.getStartRecord()).list());
		qmd.getData().put("page", qmd.getPage());
		qmd.getData().put("records",records);
		qmd.getData().put("total",(int)Math.ceil(records/(qmd.getRows()*1.0)));
	}
	
	
	@Override
	public void getEntityByEid(QueryMode<T> qmd) {
		qmd.getData().put("data", getSession().get(qmd.getT().getClass(), qmd.getId()));
	}

	@Override
	public Serializable addEntity(T t) {
		return getSession().save(t);
	}

	@Override
	public Boolean reMoveEntity(T t) {
		getSession().delete(t);
		return true;
	}
	@SuppressWarnings("unchecked")
	public Class<T> getClazz() {
		return (Class<T>) ((ParameterizedType)getClass()
				.getGenericSuperclass())
				.getActualTypeArguments()[0];
	}

	public void CommonsQuery(QueryMode<T> qmd,String totalSql, String rowSql,String prefix,String order){
		if(qmd.getSidx()!=null && qmd.getSidx().length()>0){
			 order=prefix+"."+qmd.getSidx();
		}
		Map<String, Object> data=qmd.getData();
		try{
			Long records;
			records=(Long) getSession().createQuery(totalSql).uniqueResult();
			data.put("records",records);
			data.put("total",(int)Math.ceil(records/(qmd.getRows()*1.0)));
			System.out.println(qmd.getRows());
			data.put("rows", getSession().createQuery(rowSql+order+" "+qmd.getSord()).setMaxResults(qmd.getRows()).setFirstResult(qmd.getStartRecord()).list());	
			data.put("page", qmd.getPage());
		}
		catch (Exception e) {
			e.printStackTrace();
		} 
		qmd.setData(data);
	}
	
	@SuppressWarnings("unchecked")
	public void CommonsQuery(QueryMode<T> qmd, String rowSql,String prefix,String order,Category key){
		if(qmd.getSidx()!=null && qmd.getSidx().length()>0){
			 order=prefix+"."+qmd.getSidx();
		}
		Map<String, Object> data=new HashMap<String, Object>();
		try{
			data.put("rows", getSession().createQuery(rowSql+order+" "+qmd.getSord()).setMaxResults(qmd.getRows()).setFirstResult(qmd.getStartRecord()).list());
			data.put("category", key.getCatalog());
			data.put("categoryName", key.getCategoryName());
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		if(qmd.getData().get("list")==null){
			List<Map<String,Object>> list=new ArrayList<Map<String,Object>>();
			list.add(data);
			qmd.getData().put("list", list);
			
		}
		else{
			((List<Map<String,Object>>)qmd.getData().get("list")).add(data);
		}
	}
	public T getT() {
		return t;
	}

	public void setT(T t) {
		this.t = t;
	}

	@Override
	public void getList(QueryMode<T> t) {
		String eidName=null;
		StringBuffer sb=new StringBuffer();
		Field[] f=t.getT().getClass().getDeclaredFields();
		eidName=getEidAndPackage(sb, f,eidName);
		f=t.getT().getClass().getSuperclass().getDeclaredFields();
		eidName=getEidAndPackage(sb, f,eidName);
		System.out.println(sb.substring(0, sb.length()-1));
		String totalSql="select count(t."+eidName+") from "+t.getT().getClass().getSimpleName()+" t";
		String rowSql="select new map(" +sb.substring(0, sb.length()-1)+
				") from "+t.getT().getClass().getSimpleName()+" t order by ";
		System.out.println(rowSql);
		CommonsQuery(t, totalSql, rowSql, "t", "t."+eidName);
		
	}

	private String getEidAndPackage(StringBuffer sb, Field[] f,String eidName) {
		for (Field field : f) {
			if(eidName==null && field.getAnnotation(Id.class)!=null){
				eidName=field.getName();
				sb.append("t."+field.getName()).append(" as id,");
				continue;
			}
			else if(field.getType().isPrimitive()) {
				sb.append("t."+field.getName()).append(" as "+field.getName()).append(",");
			}
			else if(field.getType().getPackage().getName().equals("com.fzb.forum4j.po")) continue;
			else if(field.getType().getPackage().getName().equals("java.util")) continue;
			sb.append("t."+field.getName()).append(" as "+field.getName()).append(",");
		}
		return eidName;
	}
	public void updateAlias(QueryMode<T> qmd, Map<String, Object> last,Map<String, Object> next){
		if(next==null){
			next=new HashMap<String, Object>();
			next.put("title", "没有下一条了");
			next.put("id", qmd.getId());
		}
		if(last==null){
			last=new HashMap<String, Object>();
			last.put("title", "没有上一条了");
			last.put("id", qmd.getId());
		}
		qmd.getData().put("last", last);
		qmd.getData().put("next", next);
	}
	
	public void queryEntityByHQL(QueryMode<T> qmd, String hql){
		qmd.getData().put("data", getSession().createSQLQuery(hql).uniqueResult());
	}
	
	protected Integer getStartRecord(Integer rows,Integer page) {
		return (page-1)*rows;
	}
	protected Integer getStartRecord(Integer page) {
		return (page-1)*5;
	}

	@Override
	public void batchDelByIds(QueryMode<T> qmd) {
		String obj=qmd.getT().getClass().getSimpleName();
		String eidName=null;
		Field[] f=qmd.getT().getClass().getDeclaredFields();
		eidName=getEidAndPackage(f,eidName);
		f=qmd.getT().getClass().getSuperclass().getDeclaredFields();
		eidName=getEidAndPackage(f,eidName);
		
		//执行批量删除
		getSession().createQuery("delete from "+obj+" t where t."+eidName+" in("+ qmd.getIds()+")").executeUpdate();
	}
	private String getEidAndPackage(Field[] f,String eidName) {
		for (Field field : f) {
			if(field.getAnnotation(Id.class)!=null){
				eidName=field.getName();
				break;
			}
		}
		return eidName;
		
	}

	@Override
	public void getListByFilters(QueryMode<T> qmd) {
		
	}
	
	public void getSimpleEntityMsg(QueryMode qmd,String msg ,String qwhere){
		Map<String,String> data=(Map) getSession().createQuery("select new map("+msg+") from "+getClazz().getSimpleName()+" t where "+qwhere).uniqueResult();
		if(data!=null){
			qmd.getData().putAll(data);
		}
	}
}
